#ifndef __SITUATION_HPP__
#define __SITUATION_HPP__

#include <string>
#include <jsoncpp/json/json.h>

#include "util.hpp"

namespace yx
{
    class Situation
    {
    protected:
        Json::Value val;
        Json::FastWriter writer;

    public:
        Situation() = default;
        virtual ~Situation() = default;
        virtual std::string what() = 0;
    };

    class SubmitCodeEmpty : public Situation
    {
    public:
        SubmitCodeEmpty() = default;
        virtual ~SubmitCodeEmpty() = default;
        virtual std::string what() override
        {
            val["status"] = -1;
            val["reason"] = "用户提交的代码为空!!!";
            return writer.write(val);
        }
    };

    class InternalError : public Situation
    {
    public:
        InternalError() = default;
        virtual ~InternalError() = default;
        virtual std::string what() override
        {
            val["status"] = -2;
            val["reason"] = "内部错误!!!";
            return writer.write(val);
        }
    };

    class CompilationFailure : public Situation
    {
    private:
        std::string _file;

    public:
        CompilationFailure(const std::string &file) : _file(file) {}
        virtual ~CompilationFailure() = default;
        virtual std::string what() override
        {
            val["status"] = -3;
            std::string desc;
            FileUtil::readFile(_file, desc);
            val["reason"] = desc;
            return writer.write(val);
        }
    };

    class RunFailure : public Situation
    {
    private:
        int _signo;

        // 运行失败需不需要将stdout及stderr返回呢???
        // static std::string CodeToDesc(int code, const std::string &file_name)
        // {}
        static std::string signoToDesc(int signo)
        {
            std::string desc;

            switch (signo)
            {
            case SIGABRT:
                desc = "内存超出范围!!!";
                break;
            case SIGXCPU:
                desc = "CPU超出使用!!!";
                break;
            case SIGFPE:
                desc = "浮点数溢出!!!";
                break;
            default:
                desc = "未知: " + std::to_string(signo);
                break;
            }
            return desc;
        }

    public:
        RunFailure(int signo) : _signo(signo) {}
        virtual ~RunFailure() = default;
        virtual std::string what() override
        {
            val["status"] = _signo;
            val["reason"] = signoToDesc(_signo);
            return writer.write(val);
        }
    };

}

#endif // __SITUATION_HPP__